package cn.bitkit.base.util;

import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 *
 * @author changbo
 *
 */
@Slf4j
public class LocalDateTimeUtil {

    public static final DateTimeFormatter DF_DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DF_DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter DF_DATE_TIME_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    public static final DateTimeFormatter DF_DATE_NUM = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter DF_DATE_TIME_NUM = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static final DateTimeFormatter DF_DATE_TIME_MS_NUM = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    public static final DateTimeFormatter DF_YEAR_MONTH_NUM = DateTimeFormatter.ofPattern("yyyyMM");

    public static LocalDateTime convertLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date convertDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static long getMilliSeconds(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static LocalDateTime toLocalDateTime(long milleSeconds){
        return Instant.ofEpochMilli(milleSeconds)
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
    }

    public static String format(LocalDateTime localDateTime, DateTimeFormatter formatter) {
        try {
            if(formatter == null || localDateTime == null) {
                return null;
            }
            return localDateTime.format(formatter);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    private static LocalDateTime parse(DateTimeFormatter formatter, String date) {
        return parse(formatter, date, false);
    }

    private static LocalDateTime parse(DateTimeFormatter formatter, String date, boolean byDate) {
        try {
            if(formatter == null || date == null) {
                return null;
            }
            if(byDate){
                return LocalDate.parse(date, formatter).atStartOfDay();
            }else{
                return LocalDateTime.parse(date, formatter);
            }
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    public static String toDate(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE);
    }

    public static String toDateTime(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE_TIME);
    }

    public static String toDateTimeMs(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE_TIME_MS);
    }

    public static String toDateNum(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE_NUM);
    }

    public static String toDateTimeNum(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE_TIME_NUM);
    }

    public static String toDateTimeMsNum(LocalDateTime localDateTime){
        return format(localDateTime, DF_DATE_TIME_MS_NUM);
    }

    public static String toYearMonthNum(LocalDateTime localDateTime){
        return format(localDateTime, DF_YEAR_MONTH_NUM);
    }


    public static LocalDateTime parseDate(String date){
        return parse(DF_DATE, date, true);
    }

    public static LocalDateTime parseDateTime(String date){
        return parse(DF_DATE_TIME, date);
    }

    public static LocalDateTime parseDateNum(String date){
        return parse(DF_DATE_NUM, date, true);
    }

    public static LocalDateTime parseDateTimeNum(String date){
        return parse(DF_DATE_TIME_NUM, date);
    }



    public static String getCurrentDate(){
        return format(LocalDateTime.now(), DF_DATE);
    }

    public static String getCurrentDateNum(){
        return format(LocalDateTime.now(), DF_DATE_NUM);
    }

    public static String getCurrentTime(){
        return format(LocalDateTime.now(), DF_DATE_TIME);
    }
    public static String getCurrentTimeNum(){
        return format(LocalDateTime.now(), DF_DATE_TIME_NUM);
    }

    public static String getCurrentTimeMsNum(){
        return format(LocalDateTime.now(), DF_DATE_TIME_MS_NUM);
    }

    public static LocalDateTime asDayStart(LocalDateTime localDateTime){
        return localDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    public static LocalDateTime asDayEnd(LocalDateTime localDateTime){
        return localDateTime.withHour(23).withMinute(59).withSecond(59).withNano(0);
    }

    public static LocalDateTime asMonthStart(LocalDateTime localDateTime){
        return localDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    public static LocalDateTime asMonthEnd(LocalDateTime localDateTime){
        return localDateTime.withHour(23).withMinute(59).withSecond(59).withNano(0);
    }


}
